#include "GridImage.h"
#include <stdio.h>
#include <stdlib.h>
#include "Solver.h"

/*
AELUTFMMRNAMWTGDOPNRIYAZNVETFOREOQUWNMTNRBENOEDOEBTZSUEWSAAOYOUNSHDLEKNGINNIRXSEQMQONIOOAIIKTSWUSISTFWEIJHWNTYFSABWNL
AELUTFMMRNAMWTGDOPNRIYAZNVETFOREOQUWNMTNRBENOEDOEBTZSUEWSAAOYOUNSHDLEKNGINNIRXSEQMQONIOOAIIKTSWUSISTFWEIJHWNTYFSABWNL
WordSoup.exe.lnk New\DSC00046.jpg
WTMCKOREQLRTSASPTPTXNMOQLBRQGMOIDSEXEESUEURTANGRLEXTOEMNZNVETXRLOSMSTOLHXENYRENRSHNYENMEAASNIRKNOETSCEXRPASGIFNMFEUET
WTMCKOREQLRTSASPTPTXNMOQLBRQGMOIDSEXEESUEURTANGRLEXTOEMNZNVETXRLOSMSTOLHXENYRENRSHNYENMEAASNIRKNOETSCEXRPASGIFNMFEUET
SUQOIIALAAPPQBOPLSWHZKXIOENTOTYMUNMSDSNKROAUAZDIVGNSEFROMIIWSTQEAAUEBWOZZEABOEPUOIIISRUHWAAERGCKMQPAZNNLURARUUKJYHNIT
SUQOIIALAAPPQBOPLSWHZKXIOENTOTYMUNMSDSNKROAUAZDIVGNSEFROMIIWSTQEAAUEBWOZZEABOEPUOIIISRUHWAAERGCKMQPAZNNLURARUUKJYHNIT
*/

#define MAXRADIFF 0.03

bool operator < (const diffs& left, const diffs& right)
{
	return (left.diff < right.diff);
}

bool operator < (const scrline& left, const scrline& right)
{
	return (left.rho < right.rho);
}

#define NETWIDTH  30
#define NETHEIGHT 30

void GridImage::Display(Grid * grid, char * Folder)
{
	printf("Display\n");
	CvSize size;
	size.width = 320;
	size.height = 240;

	char text[] = " ";

	IplImage * solution = cvCreateImage(size, IPL_DEPTH_8U, 3);

	cvZero(solution);
	
	cvThreshold(solution,solution,5,255,CV_THRESH_BINARY_INV);

	CvPoint pt1,pt2;
	CvScalar clr;

	for (int i=0;i<grid->wordlen-1;i++)
	{
		pt1.x = 25 + 18 * grid->word[i].x;
		pt1.y = 24 + 18 * grid->word[i].y;

		pt2.x = 25 + 18 * grid->word[i+1].x;
		pt2.y = 25 + 18 * grid->word[i+1].y;
		
		clr = CV_RGB(0,255,0);

		cvDrawLine(solution, pt1, pt2, clr);
	}

	for (int g=0;g<ROWS;g++)
	{
		for (int r=0;r<COLS;r++)
		{
			clr = CV_RGB(120,120,255);
			
			for (int i=0;i<grid->wordlen;i++)
			{
				if (r == grid->word[i].x && g == grid->word[i].y)
				{
					if (i == 0)
						clr = CV_RGB(255,0,0);
					else
						clr = CV_RGB(0,0,0);
				}
			}

			pt1.x = 20 + 18 * r;
			pt1.y = 30 + 18 * g;

			text[0] = grid->grid[r][g];
			cvPutText(solution, text, pt1, &fontdisp, clr);
		}
	}

	char theword[100];
	int b,points = 0;

	for (b=0;b<grid->wordlen;b++)
	{
		points += GetPoints(grid->word[b].letter);
		theword[b] = grid->word[b].letter;
	}

	points = points * (grid->wordlen);

	theword[b] = ' ';
	//itoa(points, theword + b + 1, 10);
	
	pt1.x = 20;
	pt1.y = 200;
	clr = CV_RGB(0,0,0);
	cvPutText(solution, theword, pt1, &fontdisp, clr);

	if (0 && Folder)
	{
		char filename[500];
		static int count = 0;

		sprintf(filename, "%s\\Solution%d.JPG", Folder, count);

		count++;
	
		cvSaveImage(filename, solution);
	}
	else
	{
		cvNamedWindow( "AS", 1 );
		cvShowImage( "AS", solution );
		cvWaitKey(0);
		cvDestroyWindow("AS");
	}

	cvReleaseImage( &solution );
}

GridImage::GridImage(void)
{
	char File[] = "Train/A.bmp";

	for (int o=0;o<26;o++)
	{
		File[6] = 'A' + o;
		if((letters[o]=cvLoadImage(File, 0))== 0)
		{
			printf("Couldnt load: %s\n", File);
			return;
		}
	}

	cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 2.0, 2.0, 0, 4, CV_AA);
	cvInitFont(&fontdisp, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, CV_AA);

	int numLayers = 3, lSz[3] = {NETWIDTH*NETHEIGHT,26,26};
	//double beta = 0.3, alpha = 0.1, Thresh =  0.00001;
	double beta = 0.3, alpha = 0.1;

	bp = new CBackProp(numLayers, lSz, beta, alpha);

	if (bp->load("Neural.net"))
		printf("Neural.net loaded.\n");
	else
		printf("Neural.net not loaded.\n");
}

void GridImage::Train()
{
	double datain[NETWIDTH * NETHEIGHT];
	double dataot[26];	

	CvScalar c;
	CvPoint pt1;

	//double Thresh =  0.00001;
	long num_iter = 100000000;

	printf("Starting training...\n");

	long i;
	for ( i=0; i<num_iter ; i++)
	{
		int t = rand() % 26;

		for (pt1.x=0;pt1.x<NETWIDTH;pt1.x++)
		for (pt1.y=0;pt1.y<NETHEIGHT;pt1.y++)
		{
			c = cvGetAt(letters[t], pt1.x, pt1.y);

			datain[pt1.y + pt1.x * NETWIDTH] = (c.val[0] - 128) / 128;
		}

		//for (int bit=0;bit<5;bit++)
		//	dataot[bit] = ((t) & (1 << bit));
		for (int u=0;u<26;u++)
			dataot[u] = 1*(u == t);

		bp->bpgt(datain, dataot);

		/*if( bp->mse(dataot) < Thresh) {
			printf("Network Trained. Threshold value achieved in %d iterations.\n", i);
			printf("MSE:  %f\n", bp->mse(dataot));
			break;
		}*/

		if ((i%1024) == 0 && cvWaitKey(0) == 'q')
		{
			printf("F12 Break...\n");
			break;
		}

		if ( ((i%1300) / 26) == 0 )
			printf("i: %ld\t MSE: %f\n", i, bp->mse(dataot));

	}
	
	if ( i == num_iter )
	{
		printf("Network Trained. Threshold value achieved in %ld iterations.\n", i);
		printf("MSE:  %f\n", bp->mse(dataot));
	}

	bp->save("Neural.net");
}

char GridImage::GetChar(CvRect rect, IplImage* mask)
{
	char retu = '?';
	CvSize lt,rt;
	lt.width = NETWIDTH;
	lt.height = NETHEIGHT;
	rt.width = rect.height;
	rt.height = rect.height;

	IplImage* letter = cvCreateImage( lt, 8, 1 );
	IplImage* rletter = cvCreateImage( rt, 8, 1 );

	CvPoint2D32f ptf;
	ptf.x = (float)(rect.x + rect.width / 2);
	ptf.y = (float)(rect.y + rect.height / 2);

	//cvZero(rletter);
	cvGetRectSubPix(mask, rletter, ptf);

	cvThreshold( rletter, rletter, 0.5, 255, CV_THRESH_BINARY );

	cvResize(rletter, letter);

	long diffmax = 255 * NETWIDTH * NETHEIGHT;

	//if (rect.x == 724 && rect.y == 501)	printf("%d %d\n", rect.width, rect.height);

	for (int r=0;r<26;r++)
	{
		//printf("adsf\n");
		CvScalar c,d;
		CvPoint pt1;
		long diffacc = 0;

		for (pt1.x=0;pt1.x<NETWIDTH;pt1.x++)
		for (pt1.y=0;pt1.y<NETHEIGHT;pt1.y++)
		{
			//printf("l %d %d\n", letter->width, pt1.x);
			c = cvGetAt(letter, pt1.x, pt1.y);
			//printf("i %d %d\n", letter->width, pt1.x);
			d = cvGetAt(letters[r], pt1.x, pt1.y);
			//printf("o %d %d\n", 0, pt1.x);

			int diff = (int)(c.val[0] - d.val[0]);
			if (diff < 0) diff = -diff;

			diffacc += diff;
		}


		//printf("2df\n");
		if (diffmax > diffacc)
		{
			diffmax = diffacc;
			retu = 'A' + r;
		}
	}
	//printf("osf\n");

	/*double datain[NETWIDTH * NETHEIGHT];

	CvScalar c;
	CvPoint pt1;

	for (pt1.x=0;pt1.x<NETWIDTH;pt1.x++)
	for (pt1.y=0;pt1.y<NETHEIGHT;pt1.y++)
	{
		c = cvGetAt(letter, pt1.x, pt1.y);

		datain[pt1.y + pt1.x * NETWIDTH] = (c.val[0] - 128) / 128;
	}

	double nout, max = 0;

	bp->ffwd(datain);

	for (int u=0;u<26;u++)
	{
		nout = bp->Out(u);
		if (max < nout) {
			max = nout;
			retu = 'A' + u;
		}
	}*/

	//printf("%c", 'A' + maxn);

	/*for (pt1.x=0;pt1.x<NETWIDTH;pt1.x++)
	for (pt1.y=0;pt1.y<NETHEIGHT;pt1.y++)
	{
		c = cvGetAt(let, rect.y + ((pt1.y*rect.height) / NETHEIGHT), rect.x + ((pt1.x*rect.height) / NETWIDTH));

		//printf("%f %f %f %f\n", c.val[0], c.val[1], c.val[2], c.val[3]);
		
		if (c.val[0] == 0 && c.val[2] == 255)
			cvLine(letter, pt1, pt1, CV_RGB(255,255,255), 1, 8 );
	}*/

	//cvNamedWindow( "Letter", 1 );
	//cvShowImage( "Letter", letter );
	//cvWaitKey(0);

	/*char rc = 0;
	char filen[] = "A.bmp";

	scanf_s("%c", &rc);

	if (rc >= 'A' || rc <= 'Z')
	{
		filen[0] = rc;
		//printf("%s\n", filen);
		cvSaveImage(filen, letter);
	}*/
	
	return retu;
}

bool GridImage::GetCharacters(char * buff)
{
	//
	//3264x2448 100 100 700 00
	//printf("GetChars\n");

	int numfound = 0;
	char biggrid[COLS*2+1][ROWS*2+1];
	
	CvSize masksz;
	masksz.width = sz.width + 2;
	masksz.height = sz.height + 2;

	IplImage* mask = cvCreateImage( masksz, IPL_DEPTH_8U, 1 );

	int threshx = 700;
	int threshy = 1300;

	if (sz.width < 2000) threshy = 400;

	//printf("asf\n");
	std::vector<scrline> linelistx = GetLines(1, sz.width / (13 * 2), threshx);
	std::vector<scrline> linelisty = GetLines(0, sz.height / (9 * 2), threshy);

	for (int l = 0; l < (int)linelisty.size(); l++)
	{
		
		double a = cos(linelisty[l].theta), b = sin(linelisty[l].theta);
		double x0 = a*linelisty[l].rho, y0 = b*linelisty[l].rho;

		CvPoint pt1, pt2;
		pt1.x = cvRound(x0 + 5000*(-b));
		pt1.y = cvRound(y0 + 5000*(a));
		pt2.x = cvRound(x0 - 5000*(-b));
		pt2.y = cvRound(y0 - 5000*(a));

		cvLine( draw, pt1, pt2, CV_RGB(0,255,0), 4, 8 );

	}

	for (int l = 0; l < (int)linelistx.size(); l++)
	{
		
		double a = cos(linelistx[l].theta), b = sin(linelistx[l].theta);
		double x0 = a*linelistx[l].rho, y0 = b*linelistx[l].rho;
		
		CvPoint pt1, pt2;
		pt1.x = cvRound(x0 + 5000*(-b));
		pt1.y = cvRound(y0 + 5000*(a));
		pt2.x = cvRound(x0 - 5000*(-b));
		pt2.y = cvRound(y0 - 5000*(a));

		cvLine( draw, pt1, pt2, CV_RGB(0,255,0), 4, 8 );
	}

	if (linelistx.size() < 2 || linelisty.size() < 2)
	{
		printf("Too few (%d,%d) lines found...\n", (int)linelistx.size(), (int)linelisty.size());
		return 0;
	}

	//cvSaveImage("Out.jpg", draw, 0);

	std::vector<diffs> difflist;

	std::sort(linelistx.begin(), linelistx.end());
	std::sort(linelisty.begin(), linelisty.end());

	for (int l = 0; l < (int)linelistx.size()-1; l++)
	{
		diffs temp = {linelistx[l+1].rho - linelistx[l].rho,l};
		difflist.push_back(temp);
	}
	std::sort(difflist.begin(), difflist.end());

	int diffavgxline = difflist[(difflist.size() - 1) / 2].i;
	float diffavgx = difflist[(difflist.size() - 1) / 2].diff;

	difflist.clear();

	for (int l = 0; l < (int)linelisty.size()-1; l++)
	{
		diffs temp = {linelisty[l+1].rho - linelisty[l].rho,l};
		difflist.push_back(temp);
	}
	std::sort(difflist.begin(), difflist.end());
	int diffavgyline = difflist[(difflist.size() - 1) / 2].i;
	float diffavgy = difflist[(difflist.size() - 1) / 2].diff;

	double crosspoint[2];
	
	if (!Intersect(linelistx[diffavgxline].theta, linelistx[diffavgxline].rho, linelisty[diffavgyline].theta, linelisty[diffavgyline].rho, crosspoint))
	{
		printf("Line intersection error\n");
		return 0;
	}

	//printf("Yay\n");
	crosspoint[0] += diffavgy / 2;
	crosspoint[1] += diffavgx / 2;

	double xadd = diffavgy;//*(sin(linelisty[diffavgxline].theta) + cos(linelisty[diffavgyline].theta));
	double yadd = diffavgx;//*(cos(linelisty[diffavgxline].theta) + sin(linelisty[diffavgyline].theta));

	for (int y = 0; y < (ROWS*2); y++)
	for (int x = 0; x < (COLS*2); x++)
	{
		biggrid[x][y] = 0;

		CvPoint pt1;
		pt1.x = cvRound(crosspoint[0] + (x-(COLS))*xadd);
		pt1.y = cvRound(crosspoint[1] + (y-(ROWS))*yadd);

		if ((pt1.x <= 0 || pt1.x >= sz.width) || (pt1.y <= 0 || pt1.y >= sz.width))
			continue;

		//if (x == 0 && y == 0) 	cvLine( draw, pt1, pt1, CV_RGB(0,255,0), 35, 8 ); else
			cvLine( draw, pt1, pt1, CV_RGB(255,0,0), 15, 8 );

		if (!FindNearestWhite(&pt1))
			continue;

		int lo_diff = 10;
		int up_diff = 200;

		CvConnectedComp cc2;

		//cvZero(mask);
		//printf("before\n");
		cvFloodFill(let, pt1, cvScalarAll(255)/*CV_RGB(255,0,0)*/, CV_RGB( lo_diff, lo_diff, lo_diff ),CV_RGB( up_diff, up_diff, up_diff ), &cc2, CV_FLOODFILL_MASK_ONLY|8, mask); //, ,cvScaleAll(0), cvScalarAll(0), cc2); CV_FLOODFILL_MASK_ONLY CV_FLOODFILL_FIXED_RANGE + 

		//printf("after\n");
		if (cc2.rect.width > diffavgy || cc2.rect.height > diffavgx) continue;
		if (cc2.rect.height < (diffavgx / 3)) continue;

/*		CvScalar a = cvGetAt(mask, 10, 10);
		CvScalar b = cvGetAt(mask, pt1.y, pt1.x);

		printf("%f, %f, %f, %f, %f, %f, %f, %f\n", a.val[0], a.val[1], a.val[2], a.val[3],  b.val[0], b.val[1], b.val[2], b.val[3]);

		cvNamedWindow( "Hough2" );
		cvShowImage( "Hough2", mask );
		cvWaitKey(0);*/

		//printf("L1op\n");
		char text[] = "A";
		text[0] = GetChar(cc2.rect, mask);

		//printf("Loop\n");
		//printf("(%d,%d) = %c %d %d\n", x, y, text[0], cc2.rect.x, cc2.rect.y);

		biggrid[x][y] = text[0];
		numfound++;

		cvLine( draw, pt1, pt1, CV_RGB(0,0,255), 10, 8 );

		CvPoint pt2,pt3,pt4;

		pt1.x = cc2.rect.x;
		pt1.y = cc2.rect.y;

		pt2.x = cc2.rect.x + cc2.rect.width;
		pt2.y = cc2.rect.y;
		
		pt3.x = cc2.rect.x;
		pt3.y = cc2.rect.y + cc2.rect.height;

		pt4.x = cc2.rect.x + cc2.rect.width;
		pt4.y = cc2.rect.y + cc2.rect.height;

		cvLine( draw, pt1, pt2, CV_RGB(255,255,0), 4, 8 );
		cvLine( draw, pt2, pt4, CV_RGB(255,255,0), 4, 8 );
		cvLine( draw, pt4, pt3, CV_RGB(255,255,0), 4, 8 );
		cvLine( draw, pt3, pt1, CV_RGB(255,255,0), 4, 8 );

		cvPutText(draw, text, pt2, &font, CV_RGB(255,0,255));
	}
	
	//printf("Mid\n");

	/*for (int x = 0; x < linelistx.size(); x++)
	for (int y = 0; y < linelisty.size(); y++)
	{
		if (image.Intersect(linelistx[x].theta, linelistx[x].rho, linelisty[y].theta, linelisty[y].rho, crosspoint))
		{
			CvPoint pt1;
			pt1.x = cvRound(crosspoint[0]);
			pt1.y = cvRound(crosspoint[1]);
			cvLine( image.src, pt1, pt1, CV_RGB(255,0,255), 20, 8 );
		}
	}*/

	//for (int y = 0; y < (ROWS*2 - 1); y++)
	//for (int x = 0; x < (COLS*2 - 1); x++)

	int rx=0,ry=0,maxlets = 0;

	for (int gy = 0; gy <= ROWS; gy++)
	for (int gx = 0; gx <= COLS; gx++)
	{
		int numlets = 0;

		for (int y = 0; y < ROWS; y++)
		for (int x = 0; x < COLS; x++)
		{
			if (biggrid[gx+x][gy+y]) numlets++;
		}

		if (maxlets < numlets)
		{
			maxlets = numlets;
			rx = gx;
			ry = gy;
		}
	}

	int letters = 0;
	for (int y = 0; y < ROWS; y++)
	for (int x = 0; x < COLS; x++)
	{
		buff[letters] = biggrid[rx+x][ry+y];

		if (!buff[letters])
			buff[letters] = '?';

		letters++;
	}

	buff[letters] = 0;

	if (maxlets < 117)
		printf("Only found %d letters.\n", maxlets);

	return true;
}

bool GridImage::FindNearestWhite(CvPoint * start)
{
	CvScalar c;

	for (double inc=0;inc<90;inc+=1)
	{	
		double rx = start->x + inc*cos(inc);
		double ry = start->y + inc*sin(inc);

		start->x = cvRound(rx);
		start->y = cvRound(ry);

		if ((start->x <= 0 || start->x >= sz.width) || (start->y <= 0 || start->y >= sz.height))
			return false;

		//printf("%d,%d\n", start.x, start.y);

		c = cvGetAt(let,start->y,start->x);

		if (c.val[0] == 255 && c.val[1] == 255 && c.val[2] == 255) //if (c.val[1] <= 40 && c.val[2] >= 145)
		{
			//cvLine( src, start, start, CV_RGB(255,255,0), 4, 8 );
			return true;
		}
		//else cvLine( src, start, start, CV_RGB(0,255,0), 4, 8 );
	}
	return false;
}

bool GridImage::OpenFile(char * file)
{
	if((src=cvLoadImage(file, 1))!= 0)
    {
		sz = cvGetSize(src);

		let = cvCreateImage( sz, 8, 3 );
		draw = cvCreateImage( sz, 8, 3 );
		hsv = cvCreateImage( sz, 8, 3 );
		lap = cvCreateImage( sz, 8, 1 );

		cvCopyImage(src, draw);
		cvCopyImage(src, let);
		cvCvtColor( src, lap, CV_BGR2GRAY );
		//cvLaplace(lap, src, 3);
		//cvCanny( lap, lap, 50, 50, 3);

		cvCvtColor( src, hsv, CV_BGR2HSV );

		printf("Image opened\n");
		return true;
	}
	
	return false;
}

void GridImage::Smooth(void)
{
	cvSmooth(src,src,2,7);
	cvSmooth(src,src,2,5);
	cvSmooth(src,src,2,3);
}

bool GridImage::Intersect(double l1theta, double l1rho, double l2theta, double l2rho, double * intersection)
{
	double xa = cos(l1theta)*l1rho, ya = sin(l1theta)*l1rho;
	double xb = cos(l2theta)*l2rho, yb = sin(l2theta)*l2rho;

	double x1 = xa - 6000*sin(l1theta);
	double y1 = ya + 6000*cos(l1theta);
	double x2 = xa + 6000*sin(l1theta);
	double y2 = ya - 6000*cos(l1theta);

	double x3 = xb - 6000*sin(l2theta);
	double y3 = yb + 6000*cos(l2theta);
	double x4 = xb + 6000*sin(l2theta);
	double y4 = yb - 6000*cos(l2theta);

	double denom = ((y4 - y3)*(x2 - x1)) - ((x4 - x3)*(y2 - y1));

	double nume_a = ((x4 - x3)*(y1 - y3)) - ((y4 - y3)*(x1 - x3));

	double nume_b = ((x2 - x1)*(y1 - y3)) - ((y2 - y1)*(x1 - x3));

	if(denom == 0.0f)
	{
		//Parallel lines, something has gone horribly wrong
		return 0;
	}

	double ua = nume_a / denom;
	double ub = nume_b / denom;

	if(ua >= 0.0f && ua <= 1.0f && ub >= 0.0f && ub <= 1.0f)
	{
		// Get the intersection point.
		intersection[0] = x1 + ua*(x2 - x1);
		intersection[1] = y1 + ua*(y2 - y1);

		return true;
	}
	return 0;
}

std::vector<scrline> GridImage::GetLines(bool horizontal, int separation = 15, int houghthresh = 300)
{
	std::vector<scrline> linelist;

	IplImage* med = cvCreateImage( sz, IPL_DEPTH_16S, 3 );
	IplImage* medgrey = cvCreateImage( sz, IPL_DEPTH_8U, 1 );
	
    CvMemStorage* storage = cvCreateMemStorage(0);
    CvSeq* lines = 0;
    int i;
	
	//printf("Crash %d %d %d %d\n", src->width, src->nChannels, med->width, med->nChannels);
	//printf("These %d %d %d %d\n", src->depth, src->nChannels, med->depth, med->nChannels);
	if (horizontal)
		cvSobel(src, med, 0, 1, 5);
	else
		cvSobel(src, med, 1, 0, 5);

	//printf("Deedit\n");


	cvConvertImage( med, medgrey);
	

	//printf("Deedi2\n");
	//cvSmooth(medgrey,medgrey,2,3);

	cvThreshold( medgrey, medgrey, 130, 255, CV_THRESH_BINARY );

	/*cvNamedWindow( "Hough", 0 );
    cvShowImage( "Hough", medgrey );
    cvWaitKey(0);
	*/

	//cvThreshold( dstv, dstv, 50, 255, CV_THRESH_BINARY );
		
	lines = cvHoughLines2( medgrey, storage, CV_HOUGH_STANDARD, 2, (CV_PI/180), houghthresh, 0, 0 );

	for( i = 0; i < MIN(lines->total,9999999); i++ )
	{
		float* line = (float*)cvGetSeqElem(lines,i);
		float rho = line[0];
		float theta = line[1];
		float addy = (float)(-CV_PI / 2);
		
		if (horizontal)
		{
			if ((theta + addy > MAXRADIFF) || (theta + addy < -MAXRADIFF)) continue;
		}
		else
		{
			if ((theta > MAXRADIFF) || (theta < -MAXRADIFF)) continue;
		}

		/*
		double a = cos(theta), b = sin(theta);
		double x0 = a*rho, y0 = b*rho;

		CvPoint pt1, pt2;
		pt1.x = cvRound(x0 + 5000*(-b));
		pt1.y = cvRound(y0 + 5000*(a));
		pt2.x = cvRound(x0 - 5000*(-b));
		pt2.y = cvRound(y0 - 5000*(a));
		cvLine( src, pt1, pt2, CV_RGB(255,0,0), 2, 8 );
		*/

		bool found = false;
		for (int l = 0; l < (int)linelist.size(); l++)
		{
			if ((rho < (linelist[l].rho + separation)) && (rho > (linelist[l].rho - separation)))
			{
				found = true;
				
				linelist[l].rho = (linelist[l].rho * linelist[l].avgs + rho) / (linelist[l].avgs + 1);
				linelist[l].theta = (linelist[l].theta * linelist[l].avgs + theta) / (linelist[l].avgs + 1);
				linelist[l].avgs++;

				break;
			}
		}

		if (!found)
		{
			scrline temp = {line[0],line[1],1};
			linelist.push_back(temp);
		}
	}
	/*cvNamedWindow( "Hough" );
    cvShowImage( "Hough", medgrey );
    cvWaitKey(0);
	*/

	return linelist;
}

GridImage::~GridImage(void)
{
	/*cvReleaseImage( &src );
	cvReleaseImage( &let );
	cvReleaseImage( &glet );
	cvReleaseImage( &draw );
	cvReleaseImage( &grey );
	cvReleaseImage( &hsv );
	cvReleaseImage( &lap );

	for (int z=0;z<26;z++)
		cvReleaseImage( &letters[z] );*/


	//bp->~CBackProp();

	//delete (bp);
}
